import 'dart:convert';

import 'package:app/core/event/event_bus.dart';
import 'package:app/core/net/apis.dart';
import 'package:app/core/rtc/base/call_state.dart';
import 'package:app/core/rtc/base/session_type.dart';
import 'package:app/core/rtc/base/signaling_call_back.dart';
import 'package:app/core/rtc/base/signaling_state.dart';
import 'package:app/core/rtc/impl/rtc_signaling.dart';
import 'package:app/core/rtc/impl/session.dart';
import 'package:app/core/utils/helpers/log_print.dart';
import 'package:app/core/utils/helpers/sp.dart';
import 'package:app/data/services/store_service.dart';
import 'package:app/event/event_type.dart';
import 'package:app/page/login/entity/entity_login.dart';
import 'package:app/page/rtc/logic.dart';
import 'package:app/routes/my_routes.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:sprintf/sprintf.dart';

// typedef Type Name(params);

class RtcService extends GetxService {
  StorageController controller = Get.find<StorageController>();
  StoreService _storeService = Get.find<StoreService>();
  RtcLogic _rtcLogic = Get.put(RtcLogic());
  RtcSignaling rtcSignaling;

  RtcService._internal();

  static RtcService instance;

  static getInstance() {
    if (null == instance) {
      instance = RtcService._internal();
    }
    return instance;
  }

  factory RtcService() => getInstance();

  static bool isCalling = false;

  @override
  void onInit() {
    super.onInit();
  }

  Future<RtcService> init() async {
    rtcSignaling = RtcSignaling(Apis.BASE_IP, Apis.PORT, Apis.WS_URL);

    rtcSignaling.setSignalingCallback(SignalingCallback(
      onMessageCallback: (msg) {},
      onSignalingCallback: (state) {
        switch (state) {
          case SignalingState.state_open:
            eventBus.emit(WsStatusEvent(true));
            break;
          case SignalingState.state_close:
            eventBus.emit(WsStatusEvent(false));
            break;
          case SignalingState.state_error:
            LogPrint.getInstance().printInfo('ws 连接异常');
            eventBus.emit(WsStatusEvent(false));
            break;
        }
      },
      onLocalStream: (session, stream) {
        _rtcLogic.updateLocalStream(session, stream);
      },
      onAddRemoteStream: (session, stream) {
        _rtcLogic.updateRemoteStream(session, stream);
      },
      onRemoveRemoteStream: (session, stream) {},
      onCallStateCallback: (session, callState) {
        switch (callState) {
          case CallState.state_new: // state_ring同意后 开始回复了对方offer
            isCalling
                ? LogPrint.getInstance().printError('正在通话的提示')
                : goRtcView(session);
            break;
          case CallState.state_invite:
            isCalling = true;
            break;
          case CallState.state_ring: // TODO  需要写入到对应的消息数据库
            isCalling
                ? LogPrint.getInstance().printError('正在通话的提示')
                : ringStrategy(session);
            break;
          case CallState.state_bye:
          case CallState.state_refuse:
            _rtcLogic.cancelCall(callState);
            isCalling = false;
            break;
        }
      },
    ));

    // 连接
    var bean = LoginEntity.fromJson(json.decode(controller.userInfo));
    rtcSignaling.connect(
        bean.user_name, sprintf("%s", [bean.phone]), bean.token);

    return this;
  }

  void ringStrategy(Session session) {
    LogPrint.getInstance().printDebug(
        "通话策略 ${session.pid}   ${session.sid}   ${session.sessionType}");
    String content;
    switch (session.sessionType) {
      case SessionType.SCREEN:
        content = "屏幕分享";
        break;
      case SessionType.VIDEO:
        content = "视频通话";
        break;
      case SessionType.AUDIO:
        content = "音频通话";
        break;
    }
    showCupertinoDialog(
        context: Get.overlayContext,
        builder: (_) {
          return CupertinoAlertDialog(
            title: Text("用户邀请 $content"),
            actions: [
              CupertinoDialogAction(
                  child: Text("接听"),
                  onPressed: () {
                    rtcSignaling.answerCall(
                        session.pid, session.sessionType, true);
                    Get.back();
                  }),
              CupertinoDialogAction(
                  child: Text("拒绝"),
                  isDestructiveAction: true,
                  onPressed: () {
                    rtcSignaling.answerCall(
                        session.pid, session.sessionType, false);
                    Get.back();
                  }),
            ],
          );
        });
  }

  void goRtcView(Session session) {
    String remark;
    _storeService.database.queryFriendByPhone(session.pid).then((value) {
      value[0].remark == ""
          ? remark = value[0].userName
          : remark = value[0].remark;
    });
    Get.toNamed(RouteConfig.RTC, arguments: {
      "phone": session.pid,
      "name": remark,
      "type": session.sessionType,
      "response": true,
    });
  }

  RtcSignaling get mRtcSignaling => rtcSignaling;

  @override
  void onClose() {
    eventBus?.cancel();
  }
}
